pub mod manager;
pub mod api;

pub use manager::PluginManager;
pub use api::{Plugin, PluginInfo, PluginApi};

use anyhow::Result;
use std::collections::HashMap;
use tracing::info;

/// Plugin system for CDB Studio
#[derive(Debug)]
pub struct PluginSystem {
    manager: PluginManager,
    loaded_plugins: HashMap<String, Box<dyn Plugin>>,
}

impl PluginSystem {
    /// Create a new plugin system
    pub fn new() -> Self {
        info!("Initializing plugin system");
        
        Self {
            manager: PluginManager::new(),
            loaded_plugins: HashMap::new(),
        }
    }
    
    /// Load a plugin from a file
    pub async fn load_plugin(&mut self, path: &str) -> Result<()> {
        info!("Loading plugin from: {}", path);
        
        let plugin = self.manager.load_plugin(path).await?;
        let plugin_info = plugin.info();
        
        self.loaded_plugins.insert(plugin_info.name.clone(), plugin);
        
        Ok(())
    }
    
    /// Unload a plugin
    pub fn unload_plugin(&mut self, name: &str) -> Result<()> {
        info!("Unloading plugin: {}", name);
        
        if let Some(plugin) = self.loaded_plugins.remove(name) {
            drop(plugin);
            Ok(())
        } else {
            Err(anyhow::anyhow!("Plugin not found: {}", name))
        }
    }
    
    /// Get a loaded plugin
    pub fn get_plugin(&self, name: &str) -> Option<&dyn Plugin> {
        self.loaded_plugins.get(name).map(|p| p.as_ref())
    }
    
    /// List all loaded plugins
    pub fn list_plugins(&self) -> Vec<PluginInfo> {
        self.loaded_plugins
            .values()
            .map(|plugin| plugin.info())
            .collect()
    }
    
    /// Check if a plugin is loaded
    pub fn is_plugin_loaded(&self, name: &str) -> bool {
        self.loaded_plugins.contains_key(name)
    }
    
    /// Get plugin count
    pub fn plugin_count(&self) -> usize {
        self.loaded_plugins.len()
    }
}

impl Default for PluginSystem {
    fn default() -> Self {
        Self::new()
    }
}
